package trace

import (
	"fmt"
	"github.com/google/uuid"
	"google.golang.org/grpc/metadata"
)

var (
	_ Tracer = simpleTracer{}
)

type simpleTracer struct{}

func (n simpleTracer) New(title string, opts ...Option) Trace {
	tid := uuid.New().String()
	return simpleSpan{traceID: tid}
}

func (n simpleTracer) Inject(t Trace, format interface{}, carrier interface{}) error {
	if md, ok := carrier.(metadata.MD); ok {
		if k, ok := format.(string); ok {
			md.Set(k, t.TraceID())
		}
	}
	return nil
}

func (n simpleTracer) Extract(format interface{}, carrier interface{}) (Trace, error) {
	if md, ok := carrier.(metadata.MD); ok {
		if k, ok := format.(string); ok {
			vs := md.Get(k)
			if len(vs) > 0 {
				return simpleSpan{traceID: vs[0]}, nil
			}
		}
	}
	return simpleSpan{}, fmt.Errorf("extract error")
}

type simpleSpan struct {
	traceID string
}

func (n simpleSpan) TraceID() string {
	return n.traceID
}
func (n simpleSpan) SpanID() string { return "" }

func (n simpleSpan) Fork(string, string) Trace {
	return n
}

func (n simpleSpan) IsSampled() bool {
	return false
}

func (n simpleSpan) Follow(string, string) Trace {
	return simpleSpan{}
}

func (n simpleSpan) Finish(err *error) {}

func (n simpleSpan) SetTag(tags ...Tag) Trace {
	return simpleSpan{}
}

func (n simpleSpan) SetLog(logs ...LogField) Trace {
	return simpleSpan{}
}

func (n simpleSpan) MustKeep() {}

func (n simpleSpan) Visit(func(k, v string)) {}

func (n simpleSpan) SetTitle(string) {}

func (n simpleSpan) String() string { return "" }
